﻿using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.IO;
using System;

namespace ZombieGame
{
    public class World
    {
        public List<Zombie> Zombies;
        public List<Player> Players;
        public List<Entity> Entities;
        public List<Wall> Walls;
        public List<Vector2> Spawners;
        public List<Vector2> PSpawners;
        public Texture2D Background;
        public float DropRate;
        public Vector2 Size;
        bool[,] world;
        int worldX, worldY;
        float spawnDelay;

        private World()
        {
            Entities = new List<Entity>();
            Players = new List<Player>();
            Zombies = new List<Zombie>();
            Walls = new List<Wall>();
            Spawners = new List<Vector2>();
            PSpawners = new List<Vector2>();
            worldX = ((int)Size.X + 7) / 8;
            worldY = ((int)Size.Y + 7) / 8;
            world = new bool[worldX, worldY];
            for (int x = 0; x < worldX; x++)
                for (int y = 0; y < worldY; y++)
                {
                    Rectangle r = new Rectangle(x * 8, y * 8, 8, 8);
                    for (int i = 0; i < Walls.Count; i++)
                    {
                        Wall w = Walls[i];
                        if (w.CollideRectangle(r))
                        {
                            world[x, y] = true;
                            break;
                        }
                    }
                    world[x, y] = false;
                }
        }

        public static World LoadWorld(string filename)
        {
            World nW = new World();
            FileStream str = File.Open(filename, FileMode.Open);
            BinaryReader reader = new BinaryReader(str);
            nW.DropRate = reader.ReadSingle();
            while (reader.ReadByte() != 0)
            {
                var p1 = new Vector2(reader.ReadSingle(), reader.ReadSingle());
                var p2 = new Vector2(reader.ReadSingle(), reader.ReadSingle());
                Wall w = new Wall(p1, p2);
                w.Ignore = new List<int>();
                int l = reader.ReadInt32();
                for (int i = 0; i < l; i++)
                    w.Ignore.Add(reader.ReadInt32());
                nW.Walls.Add(w);
            }
            while (reader.ReadByte() != 0)
                nW.Spawners.Add(new Vector2(reader.ReadSingle(), reader.ReadSingle()));
            while (reader.ReadByte() != 0)
                nW.PSpawners.Add(new Vector2(reader.ReadSingle(), reader.ReadSingle()));
            byte[] imgData = reader.ReadBytes((int)(str.Length - str.Position));
            using (MemoryStream str2 = new MemoryStream(imgData))
                nW.Background = Texture2D.FromStream(ZombieGame.Current.GraphicsDevice, str2);
            nW.Size = new Vector2(nW.Background.Width, nW.Background.Height);
            reader.Close();
            str.Close();
            return nW;
        }

        public void Update(GameTime time)
        {
            for (int i = 0; i < Entities.Count; i++)
            {
                Entity e = Entities[i];
                e.Update(time);
            }
            for (int i = 0; i < Zombies.Count; i++)
            {
                Zombie e = Zombies[i];
                e.Update(time);
            }
            for (int i = 0; i < Players.Count; i++)
            {
                Player e = Players[i];
                e.Update(time);
            }
            spawnDelay += (float)time.ElapsedGameTime.TotalSeconds;
            if (spawnDelay > 1f / (ZombieGame.Playtime.Elapsed.TotalMinutes + 1f))
            {
                if (ZombieGame.Random.Next() % 10 == 0 && Zombies.Count < 64)
                {
                    Zombie z = new Zombie();
                    z.Position = Spawners[ZombieGame.Random.Next() % Spawners.Count];
                    z.Speed = (float)Math.Max(ZombieGame.Random.NextDouble(), 0.5f);
                    z.Health = ZombieGame.Playtime.Elapsed.Minutes + 1f;
                    Zombies.Add(z);
                }
                spawnDelay = 0f;
            }
        }

        public void Draw(SpriteBatch batch)
        {
            if (Background != null)
                batch.Draw(Background, new Vector2(), null, Color.White, 0f, new Vector2(), 1f, SpriteEffects.None, 1f);
            //foreach (Wall w in Walls) w.Draw(batch);
            for (int i = 0; i < Entities.Count; i++)
            {
                Entity e = Entities[i];
                e.Draw(batch);
            }
            for (int i = 0; i < Zombies.Count; i++)
            {
                Zombie e = Zombies[i];
                e.Draw(batch);
            }
            for (int i = 0; i < Players.Count; i++)
            {
                Player e = Players[i];
                e.Draw(batch);
            }
        }

        //public Vector2[] FindPath(Vector2 start, Vector2 target)
        //{
        //    Pathfinder finder = new Pathfinder(start / 8f, target / 8f, world);

        //}
    }
}
